package com.tushare.controller;

import com.tushare.call.StockBasicCall;
import com.tushare.call.StockInfoCall;
import com.tushare.dto.StockInfoDto;
import com.tushare.entity.*;
import com.tushare.model.KDJRange;
import com.tushare.model.KdjExtremeSelling;
import com.tushare.model.MacdRange;
import com.tushare.model.StockIndex;
import com.tushare.service.*;
import com.tushare.util.StockIndexUtil;
import net.minidev.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@RestController
@CrossOrigin("*")
public class AnalyseController {
    @Autowired
    IDailyService dailyService;
    @Autowired
    IDailyBasicService dailyBasicService;
    @Autowired
    IStockBasicService stockBasicService;
    @Autowired
    IAnalyseService analyseService;
    @Autowired
    IHkHoldService hkHoldService;
    @Autowired
    IHighStockService highStockService;
    @Autowired
    IStkHolderNumberService stkHolderNumberService;
    @Resource(name = "testFxbDrawExecutor")
    ExecutorService asyncService;
    private final AtomicInteger atomicInteger = new AtomicInteger(-1);

    /* 超跌且底量 */
    @GetMapping("oversold")
    public void oversold() {
        int initDate = 20160101;
        List<StockInfoDto> filterStockInfoDtoList = this.stockBasicService.getAllStockInfoDto().stream()
                .filter(stockInfoDto -> "主板".equals(stockInfoDto.getMarket())) // 主板
                .filter(stockInfoDto -> stockInfoDto.getPe() > 1 && stockInfoDto.getPe() < 40) // pe在（1-40）
                .filter(stockInfoDto -> stockInfoDto.getPe_ttm() > 1 && stockInfoDto.getPe_ttm() < 40) // pe在（1-40）
                .filter(stockInfoDto -> stockInfoDto.getTotal_mv() > 100 * 10000) // 市值大于 100亿
                .collect(Collectors.toList());
        atomicInteger.set(0);
        filterStockInfoDtoList.forEach(stockBasic -> asyncService.submit(new StockInfoCall(stockBasic) {
            @Override
            public StockInfoDto call() throws Exception {
                System.out.println("oversold\ttotal:" + filterStockInfoDtoList.size() + "\tcurrent:" + atomicInteger.get());
                StockInfoDto stockInfoDto = getStockInfoDto();
                List<Daily> dailyList = dailyService.getDailyListByTsCode(stockInfoDto.getTs_code(), initDate);
                List<StockIndex> stockIndexList = StockIndexUtil.cal(dailyList);
                MacdRange macdDeviate = StockIndexUtil.calMacdDeviate(stockIndexList);
                KDJRange kdjDeviate = StockIndexUtil.calKDJDeviate(stockIndexList);
                KDJRange kdjPriceDeviate = StockIndexUtil.calKDJPriceDeviate(stockIndexList);
                KdjExtremeSelling kdjExtremeSelling = StockIndexUtil.calKDJExtremeSelling(stockIndexList);
                List<HkHold> hkHoldList = hkHoldService.getTopHkHoldList(stockInfoDto.getTs_code(), 10);
                int incrementDay = -1;
                if (hkHoldList != null && hkHoldList.size() > 2) {
                    HkHold lastHold = hkHoldList.get(0);
                    for (HkHold hold : hkHoldList) {
                        if (hold.getVol() <= lastHold.getVol()) {
                            incrementDay++;
                            lastHold = hold;
                            continue;
                        }
                        break;
                    }
                }

                if (macdDeviate != null && incrementDay != 0) {
                    Analyse analyse = new Analyse();
                    analyse.setTs_code(macdDeviate.getTs_code());
                    analyse.setTrade_date(macdDeviate.getEnd_date());
                    analyse.setDeviate_ratio(macdDeviate.getDeviate_ratio());
                    analyse.setIncrement_day(incrementDay);
                    analyse.setNorm("calMacdDeviate");
                    analyse.setRemark(macdDeviate.getRemark());
                    analyseService.saveAnalyse(analyse);
                }
                if (kdjDeviate != null && incrementDay != 0) {
                    Analyse analyse = new Analyse();
                    analyse.setTs_code(kdjDeviate.getTs_code());
                    analyse.setTrade_date(kdjDeviate.getEnd_date());
                    analyse.setDeviate_ratio(kdjDeviate.getDeviate_ratio());
                    analyse.setIncrement_day(incrementDay);
                    analyse.setNorm("calKDJDeviate");
                    analyse.setRemark(kdjDeviate.getRemark());
                    analyseService.saveAnalyse(analyse);
                }
                if (kdjPriceDeviate != null && incrementDay != 0) {
                    Analyse analyse = new Analyse();
                    analyse.setTs_code(kdjPriceDeviate.getTs_code());
                    analyse.setTrade_date(kdjPriceDeviate.getEnd_date());
                    analyse.setDeviate_ratio(kdjPriceDeviate.getDeviate_ratio());
                    analyse.setIncrement_day(incrementDay);
                    analyse.setNorm("kdjPriceDeviate");
                    analyse.setRemark(kdjPriceDeviate.getRemark());
                    analyseService.saveAnalyse(analyse);
                }
                if (kdjExtremeSelling != null && incrementDay != 0) {
                    Analyse analyse = new Analyse();
                    analyse.setTs_code(kdjExtremeSelling.getTs_code());
                    analyse.setTrade_date(kdjExtremeSelling.getTrade_date());
                    analyse.setDeviate_ratio(0.0);
                    analyse.setIncrement_day(incrementDay);
                    analyse.setNorm("kdjExtremeSelling");
                    analyse.setRemark(kdjExtremeSelling.getRemark());
                    analyseService.saveAnalyse(analyse);
                }
                atomicInteger.incrementAndGet();
                return stockInfoDto;
            }
        }));
    }

    /* Macd底背离 */
    @GetMapping("rising_falling_volume")
    public String risingFallingVolume() {
        if (atomicInteger.get() != -1) {
            return "正在计算中";
        }
        atomicInteger.set(0);
        List<StockBasic> stockBasicList = stockBasicService.getAllStockBasic();
        List<StockBasic> returnList = new ArrayList<>();
        for (StockBasic stockBasic : stockBasicList) {
            asyncService.submit(new StockBasicCall(stockBasic) {
                @Override
                public StockBasic call() throws Exception {
                    StockBasic basic = getStockBasic();
                    if (consoleSingleRisingFallingVolume(basic)) {
                        returnList.add(basic);
                    }
                    atomicInteger.incrementAndGet();
                    if (atomicInteger.get() == stockBasicList.size()) {
                        System.out.println("----------------------------------");
                        System.out.println(JSONArray.toJSONString(returnList));
                        System.out.println("----------------------------------");
                        atomicInteger.set(-1);
                    }
                    return basic;
                }
            });
        }
        return "已开启线程池计算";
    }

    /* 统计十天公布一次股东人数的股票 */
    @GetMapping("cal_high_stock")
    public List<HighStock> calHighStock() {
        int year = Calendar.getInstance().get(Calendar.YEAR);
        int month = Calendar.getInstance().get(Calendar.MONTH);
        int beginDate, endDate;
        if (month >= 1) {
            beginDate = year * 10000 + month * 100 + 1;
            endDate = year * 10000 + month * 100 + 31;
        } else {
            beginDate = (year - 1) * 10000 + 1201;
            endDate = (year - 1) * 10000 + 1231;
        }
        int number = 0;
        String preTsCode = "";
        List<StkHolderNumber> holderNumberList = stkHolderNumberService.getHighStock(beginDate, endDate);
        List<HighStock> highStockList = new ArrayList<>();
        for (StkHolderNumber holderNumber : holderNumberList) {
            if (holderNumber.getTs_code().equals(preTsCode)) {
                number++;
            } else {
                number = 1;
                preTsCode = holderNumber.getTs_code();
            }
            if (number >= 2) {
                HighStock highStock = new HighStock();
                highStock.setTs_code(holderNumber.getTs_code());
                highStockList.add(highStock);
            }
        }
        highStockService.deleteAllHighStock();
        highStockService.saveOrUpdateBatch(highStockList);
        return highStockList;
    }

    @GetMapping("reduce_stock_holder")
    public List<StockInfoDto> reduceStockHolder() {
        List<StockInfoDto> stockInfoDtoList = new ArrayList<>();
        stockBasicService.getAllHighStockInfoDto().stream()
                .filter(stockInfoDto -> "主板".equals(stockInfoDto.getMarket()) && stockInfoDto.getList_date() < 20230101)
                .forEach(stockInfoDto -> {
                    List<StkHolderNumber> stkHolderNumberList = stkHolderNumberService.getStkHolderNumberByTsCode(stockInfoDto.getTs_code(), 20000101);
                    if (stkHolderNumberList.size() < 2) {
                        return;
                    }
                    StkHolderNumber currentNumber = stkHolderNumberList.get(0);
                    StkHolderNumber holderNumber = stkHolderNumberList.get(0);
                    for (StkHolderNumber number : stkHolderNumberList) {
                        if (number.getHolder_num() < holderNumber.getHolder_num()) {
                            break;
                        }
                        holderNumber = number;
                    }
                    double ratio = 1.0 * holderNumber.getHolder_num() / currentNumber.getHolder_num();
                    if (ratio > 1.2) {
                        stockInfoDtoList.add(stockInfoDto);
                    }
                });
        return stockInfoDtoList;
    }

    private boolean consoleSingleRisingFallingVolume(StockBasic stockBasic) {
        List<DailyBasic> dailyBasicList = dailyBasicService.getLastDailyBasics(stockBasic.getTs_code(), 5);
        DailyBasic initDailyBasic = dailyBasicList.remove(0);
        for (DailyBasic dailyBasic : dailyBasicList) {
            // 剔除亏损和高估的
            if (dailyBasic.getPe() < 1 || dailyBasic.getPe() > 60) {
                return false;
            } else if (dailyBasic.getTurnover_rate_f() > 5) { // 剔除高换手率的
                return false;
            } else if (dailyBasic.getClose() > initDailyBasic.getClose() && initDailyBasic.getTurnover_rate() < dailyBasic.getTurnover_rate()) {
                // 下跌缩量
                continue;
            } else if (dailyBasic.getClose() < initDailyBasic.getClose() && initDailyBasic.getTurnover_rate() > dailyBasic.getTurnover_rate()) {
                // 上涨增量
                continue;
            } else {
                return false;
            }
        }
        return true;
    }


}
